package com.mxx.common.flow;

import java.util.HashMap;
import java.util.Map;

/**
 * @author: mxx
 * @date: 2021/12/31
 * @time: 11:24
 * @Description: 描述信息
 */

public abstract class AbstractFlowManager<T extends AbstractFlowManager> implements FlowManager<T> {


    protected Map<String, FlowModule> moduleMap;

    public AbstractFlowManager() {
        this.moduleMap = new HashMap<>();
    }

    public AbstractFlowManager(Map<String, FlowModule> moduleMap) {
        this.moduleMap = moduleMap;
    }

    public T register(FlowModule flowModule) {
        this.moduleMap.put(flowModule.getActive().eventName(), flowModule);
        return (T) this;
    }


    protected void init(Flows flows, FlowContext context) throws FlowException {
        while (flows.hasNext()) {
            Flow flow = flows.next();
            try {
                flow.init(context);
            } catch (Exception ex) {
                throw new FlowException(context.tradId(), flow, "init", context, ex);
            }
            if (context.hasNext()) {
                context.resetNext();
            } else {
                break;
            }
        }
        flows.reset();
    }

    protected void execute(Flows flows, FlowContext context) throws FlowException {
        while (flows.hasNext()) {
            Flow flow = flows.next();
            try {
                flow.execute(context);
            }catch (Exception ex) {
                throw new FlowException(context.tradId(), flow, "execute", context, ex);
            }
            if (context.hasNext()) {
                context.resetNext();
            } else {
                break;
            }
        }
        flows.reset();
    }

    protected void complete(Flows flows, FlowContext context) throws FlowException {
        while (flows.hasNext()) {
            Flow flow = flows.next();
            try {
                flow.complete(context);
            } catch (Exception ex) {
                throw new FlowException(context.tradId(), flow, "complete", context, ex);
            }
            if (context.hasNext()) {
                context.resetNext();
            } else {
                break;
            }
        }
        flows.reset();
    }

    protected void canException(Flows flows, FlowContext context, Throwable throwable) {
        while (flows.hasNext()) {
            Flow flow = flows.next();
            flow.canException(context, throwable);
            boolean next = context.hasNext();
            context.resetNext();
            if (!next) {
                break;
            }
        }
        flows.reset();

    }
}
